package com.qf.test.controller;

import com.qf.test.annotation.RequiresPermissionsDesc;
import com.qf.test.service.GoodsProductService;
import com.qf.test.service.GoodsService;
import com.qf.test.service.OrderService;
import com.qf.test.service.UserService;
import com.qf.test.util.ResponseUtil;
import com.qf.test.vo.*;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.math.BigDecimal;
import java.util.*;

//表明这是一个控制层
@RestController
//解决前后端分离跨域的访问问题
@CrossOrigin("*")
@RequestMapping("/dashboard")

public class IndexController {
    @Autowired

    private UserService userService;
    @Autowired
    private GoodsService goodsService;
    @Autowired
    private GoodsProductService goodsProductService;
    @Autowired
    private OrderService orderService;

    /**
     * 首页数据统计
     * 统计User用户数 SPU商品数量 SKU货品数量  Order数量
     */
    @GetMapping("")
    //具有管理员 商品模块 查询权限才能访问
    @RequiresPermissions("admin:goods:list")
    //具有 系统管理 或商品管理  或者订单管理的查询权限 才能够访问这个方法
    @RequiresPermissionsDesc(menu = {"系统管理", "商品管理", "订单管理"}, button = "查询")
    public Object dashboard() {
        //1. 统计用户数量
        int userCount = userService.countUser();

        //2. 统计商品数量
        int goodsCount = goodsService.countGoods();

        //3. 统计货品数量
        int productCount = goodsProductService.countGoodsProduct();

        //4. 统计订单数量
        int orderCount = orderService.countOrder();

        //5. 将统计的数据封装到map中, 返回
        Map<String, Object> data = new HashMap<>();
        data.put("userTotal", userCount);
        data.put("goodsTotal", goodsCount);
        data.put("productTotal", productCount);
        data.put("orderTotal", orderCount);

        return ResponseUtil.ok(data);

    }

    /**
     * 统计首页需要的图标数据返回
     */
    @RequestMapping("/chart")
    public Object chart() {
        //1.统计多少天内的用户增长量
        List<DayStatis> userCount = userService.incrCount();

        //2.统计多少天内的商品销售额和销售量
        List<DayStatis> goodsCount = orderService.incrCount();
        //3.根据分类统计 每个商品的销售额
        List<CategorySellAmts> categoryCount = orderService.categoryCount();
        //4.合并两个统计 结果中的日期数据
        //TODO
        String[] dayData = unionDayData(userCount, goodsCount);
        //转换合并数据 需要合并日期，用户数据 订单数据
        UserOrderCntVo userOrderCntVo = new UserOrderCntVo();
        //用户数据 合并日期和用户数据的统计结果
        userOrderCntVo.setUserCnt(fetchaArrayCnt(dayData, userCount));
        //订单数据
        userOrderCntVo.setOrderCnt(fetchaArrayCnt(dayData, goodsCount));
        //日期数据
        userOrderCntVo.setDayData(dayData);
        //转换为前端需要的数据  日期 订单数量  订单金额
        OrderAmtsVo orderAmtsVo = fetchOrderAmtVo(goodsCount);
        //封装到Map中
        Map<String, Object> data = new HashMap<>();
        data.put("categorySell", categoryCount);
        data.put("orderAmts", orderAmtsVo);
        data.put("userOrderCnt", userOrderCntVo);


        return ResponseUtil.ok(data);
    }

    /**
     * 补全日期数据
     */
    private String[] unionDayData(List<DayStatis> userCount, List<DayStatis> goodsCount) {
        Set<String> date = new HashSet<>();
        //将用户的日期数据 放入到set集合中
        for (DayStatis dayStatis : userCount) {
            date.add(dayStatis.getDayStr());
        }
        for (DayStatis dayStatis : goodsCount) {
            date.add(dayStatis.getDayStr());
        }
        //将set中的日期数据过滤重复后 放入list结合中
        List<String> list = new ArrayList<>(date);

        //对数据进行排序
        Collections.sort(list);
        System.out.println(list.toString() + "1111111111111111111111111111111111111111111111111111111");
        //将list集合转换成数组返回
        return list.toArray(new String[0]);
    }

    /**
     * 统计集合中获取订单的数量 用户数量 如果对应的日期没有统计的数据 则设置为0
     */
    private int[] fetchaArrayCnt(String[] dayDate, List<DayStatis> dayStatisCnts) {
        //设置存放统计订单数量的数组 和日期数组同样的长度
        int[] arrCnts = new int[dayDate.length];
        //遍历日期数组
        for (int i = 0; i < dayDate.length; i++) {
            //订单量 默认为0
            int daycnt = 0;
            //当前循环出的字符串数组
            String DayStr = dayDate[i];
            //遍历日期订单统计的集合数据
            for (DayStatis dayStatisCnt : dayStatisCnts) {
                if (DayStr.equals(dayStatisCnt.getDayStr())) {
                    //如果数组中的日期集合中的日期对应 那么拿出对应的统计订单数
                    //赋值非上面的声明的全局数组
                    daycnt = dayStatisCnt.getCnts();
                    //跳出循环
                    break;
                }
            }

            arrCnts[i] = daycnt;

        }
        return arrCnts;

    }

    /**
     * 统计封装订单的销售和订单数量数据
     * orderCnts
     */
    private OrderAmtsVo fetchOrderAmtVo(List<DayStatis> orderCnts) {
        OrderAmtsVo vo = new OrderAmtsVo();
        //传入统计数据集合大小
        int size = 0;
        if (orderCnts != null && orderCnts.size() > 0) {
            size = orderCnts.size();
        }
        //用来存放日期数据
        String[] dayData = new String[size];
        //用来存订单数量
        int[] orderData = new int[size];
        //用来存订单每天总金额
        BigDecimal[] moneyData = new BigDecimal[size];
        //遍历统计的集合数据 获取日期 订单数量 订单金额
        for (int i = 0; i < size; i++) {
            dayData[i] = orderCnts.get(i).getDayStr();
            orderData[i] = orderCnts.get(i).getCnts();
            moneyData[i] = orderCnts.get(i).getAmts();
        }
        vo.setDayData(dayData);
        vo.setOrderCntData(orderData);
        vo.setOrderAmtData(moneyData);
        return vo;


    }

    /**
     * 封装前端需要的根据分类统计 销售的实体数据
     */
    private CategorySellVo fetchCategorySell(List<CategorySellAmts> categoryCount) {
        CategorySellVo vo = new CategorySellVo();
        if (categoryCount == null || categoryCount.size() == 0) {
            return vo;
        }
        String[] categoryNameArray = new String[categoryCount.size()];
        if (categoryCount != null) {
            for (int i = 0; i < categoryCount.size(); i++) {
                //获取分类的名字 赋值给分类名字数组
                categoryNameArray[i] = categoryCount.get(i).getName();

            }
        }
        //分类名字数组
        vo.setCategoryNames(categoryNameArray);
        //分类名字和统计的金额数据
        return vo;

    }
}
